package com.subway.babynote.db;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import com.subway.babynote.db.TableInfoList.TableInfo;
import com.subway.babynote.syncdata.ClientDataRecord;
import com.subway.babynote.syncdata.ClientDataRecordBase;
import com.subway.babynote.syncdata.StringUtil;
import com.subway.babynote.syncdata.errMessage;
import com.subway.babynote.syncdata.tableName;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public abstract class querybase extends cursorbase{
	SQLiteDatabase db = null;
	protected String tn = null;
	protected boolean is_ts2 = false;
	protected boolean select_1 = true;
	private TableInfo ti = null;
	
	static Map<String, querybase> qbm = new TreeMap<String, querybase>();
	public querybase(SQLiteDatabase _db)
	{
		this.db = _db;
		this.set_table();
		ti = TableInfoList.instance.getsqls(tn);
		if(ti==null)
			logging.err("querybase init","can not get tableinfo" );
	}
	
	public String get_tablename()
	{
		return tn;
	}
	
	public static querybase getinstance(String tablename, SQLiteDatabase _db)
	{
		if (!qbm.containsKey(tablename))
		{
			querybase qb =  newinstance(tablename,_db);
			qbm.put(tablename,qb);
		}
		return qbm.get(tablename);
	}
	
	public static querybase newinstance(String tablename, SQLiteDatabase _db)
	{
		querybase qb = null;
		if(tablename.equals(tableName.t_avg_height))
			qb = new query_h_avg(_db);
		else if(tablename.equals(tableName.t_ourcontact))
			qb = new query_contact(_db);
		else if(tablename.equals(tableName.t_feeds))
			qb = new query_feed(_db);
		else if(tablename.equals(tableName.t_feedbacks))
			qb = new query_feedback(_db);
		else if(tablename.equals(tableName.t_food_default))
			qb = new query_food_default(_db);
		else if(tablename.equals(tableName.t_food_ux))
			qb = new query_food_ux(_db);
		else if(tablename.equals(tableName.t_foods))
			qb = new query_foods(_db);
		else if(tablename.equals(tableName.t_h_default))
			qb = new query_h_default(_db);
		else if(tablename.equals(tableName.t_h_ux))
			qb = new query_h_ux(_db);
		else if(tablename.equals(tableName.t_huser))
			qb = new query_huser(_db);
		else if(tablename.equals(tableName.t_local_avg))
			qb = new query_last_avg(_db);
		else if(tablename.equals(tableName.t_loadinfo))
			qb = new query_loadinfo(_db);
		else if(tablename.equals(tableName.t_tips))
			qb = new query_tip(_db);
		else if(tablename.equals(tableName.t_users))
			qb = new query_users(_db);
		else if(tablename.equals(tableName.t_w_default))
			qb = new query_w_default(_db);
		else if(tablename.equals(tableName.t_w_ux))
			qb = new query_w_ux(_db);
		else if(tablename.equals(tableName.t_weibo))
			qb = new query_weibo(_db);
		else if(tablename.equals(tableName.t_wuser))
			qb = new query_wuser(_db);
		return qb;
	}
	
	protected abstract void set_table();
	//insert interface
	public int insert(ClientDataRecordBase crb, boolean delete_old)
	{
		int iret = -1;
		if(delete_old)
		{
			iret = this.delete();
		}
		if(iret > 0)
		{
			if(crb.get_type() == ClientDataRecordBase.ClientDataRecord_TYPE.list)
			{
				ClientDataRecord.list_ClientDataRecord lcdr = (ClientDataRecord.list_ClientDataRecord) crb;
				Iterator<ClientDataRecordBase> it = lcdr.list.iterator();
				while(it.hasNext())
				{
					ClientDataRecordBase c = it.next();
					iret = this.insert_1row(c);
					logging.err("error insert_1row", StringUtil.int2str(iret));
				}
			}
			else
			{
				if(crb.get_type() == ClientDataRecordBase.ClientDataRecord_TYPE.map)
					iret = errMessage.err_inputparam.errcode;
				else
					iret = this.insert_1row(crb);
			}
		}
		return iret;
	}
	//update one row
	public int update(ClientDataRecordBase crb)
	{
		int iret = -1;
		if(ti.updatesql == null)
			return iret;
		String[] strs = this.getUpdateParam(crb);
		if(strs == null)
			return iret;
		try
		{
			logging.info("querybase update", strs.toString());
			db.execSQL(ti.updatesql, strs);
			iret = 0;
		}
		catch(Exception ex)
		{
			logging.err("querybase update", ex.getMessage());
			iret = -1;
		}
		return iret;
	}

	protected abstract String[] getUpdateParam(ClientDataRecordBase crb);
	//get records, list format
	public ClientDataRecordBase select(ClientDataRecordBase crb)
	{
		if(ti.selectsql == null)
			return null;
		String[] strs = this.getSelectParam(crb);
		
		ClientDataRecordBase ret = null;
		Cursor cs  = null;
		try
		{
			cs = db.rawQuery(ti.selectsql, strs);
			if(cs.getCount() > 0)
			{
				cs.moveToFirst();
				if(this.select_1) //only 1 line
				{
					ret = this.read(cs);
				}
				else
				{
					ret = new ClientDataRecord.list_ClientDataRecord();
					ClientDataRecord.list_ClientDataRecord ret2 = (ClientDataRecord.list_ClientDataRecord) ret;
					while(!cs.isAfterLast())
					{
						ClientDataRecordBase r = this.read(cs);
						if(r != null)
							ret2.list.add(r);
						cs.moveToNext();
					}
				}
			}
		}
		catch(Exception ex)
		{
			logging.err("querybase select", ex.getMessage());
			ret = null;
		}
		finally
		{
			this.releaseCursor(cs);
		}
		return ret;
	}
	
	
	protected abstract String[] getSelectParam(ClientDataRecordBase crb);
	protected abstract ClientDataRecordBase read(Cursor cs);
	
	//insert 1row
	private int insert_1row(ClientDataRecordBase crb)
	{
		int iret = -1;
		if(ti.insertsql == null)
			return iret;
		String[] strs = this.getInsertParam(crb);
		if(strs == null)
			return iret;
		try
		{
			logging.info("querybase insert_1row", strs.toString());
			db.execSQL(ti.insertsql, strs);
			iret = 0;
		}
		catch(Exception ex)
		{
			logging.err("querybase insert_1row", ex.getMessage());
			iret = -1;
		}
		return iret;
	}
	protected abstract String[] getInsertParam(ClientDataRecordBase crb);
	
	public ClientDataRecordBase getts()
	{
		ClientDataRecordBase crb = this.is_ts2 ?
				(new ClientDataRecord.list_ClientDataRecord())
				: (new ClientDataRecord.ts());
		String tssql = this.is_ts2? ti.get_tssql2(): ti.get_delsql();
		Cursor cs  = null;
		try
		{
			cs = db.rawQuery(tssql, null);
			if(cs.getCount() > 0)
			{
				cs.moveToFirst();
				
				while(!cs.isAfterLast())
				{
					if(this.is_ts2)
					{
						ClientDataRecordBase r = this.getts2(cs);
						if(r != null)
						{
							((ClientDataRecord.list_ClientDataRecord)crb).list.add(r);
						}
						else
							logging.err("querybase getts", "getts2 return null");
					}
					else
					{
						crb = this.getts1(cs);
					}
					cs.moveToNext();
				}
			}
		}
		catch(Exception ex)
		{
			logging.err("querybase delete", ex.getMessage());
			crb = null;
		}
		return crb;
	}
	
	protected ClientDataRecordBase getts1(Cursor cs)
	{
		ClientDataRecord.ts t = new ClientDataRecord.ts();
		t.ts = cs.getInt(0);
		return t;
	}
	protected ClientDataRecordBase getts2(Cursor cs)
	{
		ClientDataRecord.ts t = new ClientDataRecord.ts();
		t.ts = cs.getInt(0);
		t.client_id = cs.getInt(1);
		return t;
	}
	
	public int delete()
	{		
		int iret = -1;
		String delsql = ti.get_delsql();
		try
		{
			db.execSQL(delsql);
			iret = 0;
		}
		catch(Exception ex)
		{
			logging.err("querybase delete", ex.getMessage());
			iret = -1;
		}
		return iret;
	}
	
	public int delete_1row(int _id)
	{
		int iret = -1;
		String delsql = ti.get_delsql_1row();
		try
		{
			String strs[] = new String[]{
					StringUtil.int2str(0),
					StringUtil.int2str(StringUtil.now()),
					StringUtil.int2str(_id)
			};
			db.execSQL(delsql, strs);
			iret = 0;
		}
		catch(Exception ex)
		{
			logging.err("querybase delete", ex.getMessage());
			iret = -1;
		}
		return iret;
	}
	
}
